package handler

import (
	"net/http"
	"strconv"

	"fitness/go-admin/internal/model"
	"fitness/go-admin/internal/service"
	"fitness/go-admin/pkg/response"

	"github.com/gin-gonic/gin"
)

// CheckinHandler 签到处理器
type CheckinHandler struct {
	checkinService service.CheckinService
}

// NewCheckinHandler 创建签到处理器实例
func NewCheckinHandler(checkinService service.CheckinService) *CheckinHandler {
	return &CheckinHandler{
		checkinService: checkinService,
	}
}

// ==================== 会员签到接口 ====================

// CreateCheckin 会员进馆签到
// @Summary 会员进馆签到
// @Description 会员进入健身房时打卡签到，支持GPS定位和二维码扫描双重验证
// @Tags 签到打卡
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param checkin body model.CheckinReq true "签到请求参数"
// @Success 200 {object} response.Response{data=model.CheckinResp}
// @Failure 400 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /api/v1/checkins [post]
func (h *CheckinHandler) CreateCheckin(c *gin.Context) {
	var req model.CheckinReq
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, http.StatusBadRequest, "参数错误: "+err.Error())
		return
	}

	// 从上下文中获取用户ID（实际项目中从token解析）
	userID := uint(1) // 示例值，实际应从token中获取

	// 如果是会员自签，memberID就是userID对应的会员
	// 如果是前台代签，需要传入memberID
	memberID := userID
	if req.MemberID != nil {
		memberID = *req.MemberID
	}

	resp, err := h.checkinService.CreateCheckin(userID, memberID, &req)
	if err != nil {
		response.Error(c, http.StatusInternalServerError, err.Error())
		return
	}

	response.Success(c, resp, "签到成功")
}

// CreateCheckout 会员离馆签退
// @Summary 会员离馆签退
// @Description 会员离开健身房时打卡签退，自动计算本次锻炼时长
// @Tags 签到打卡
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param checkout body model.CheckoutReq true "签退请求参数"
// @Success 200 {object} response.Response{data=model.CheckoutResp}
// @Failure 400 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /api/v1/checkins/checkout [post]
func (h *CheckinHandler) CreateCheckout(c *gin.Context) {
	var req model.CheckoutReq
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, http.StatusBadRequest, "参数错误: "+err.Error())
		return
	}

	// 从上下文中获取用户ID
	userID := uint(1) // 示例值，实际应从token中获取

	// 如果是会员自签，memberID就是userID对应的会员
	// 如果是前台代签，需要传入memberID
	memberID := userID
	if req.MemberID != nil {
		memberID = *req.MemberID
	}

	resp, err := h.checkinService.CreateCheckout(userID, memberID, &req)
	if err != nil {
		response.Error(c, http.StatusInternalServerError, err.Error())
		return
	}

	response.Success(c, resp, "签退成功")
}

// GetMyCheckins 我的签到记录
// @Summary 我的签到记录
// @Description 获取当前会员的签到历史记录，支持按日期范围筛选
// @Tags 签到打卡
// @Produce json
// @Security ApiKeyAuth
// @Param page query int false "页码（默认1）"
// @Param pageSize query int false "每页数量（默认10，最大100）"
// @Param startDate query string false "开始日期（YYYY-MM-DD）"
// @Param endDate query string false "结束日期（YYYY-MM-DD）"
// @Param type query int false "类型筛选（1:进馆签到 2:离馆签退）"
// @Success 200 {object} response.Response{data=model.CheckinListResp}
// @Failure 400 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /api/v1/checkins/my [get]
func (h *CheckinHandler) GetMyCheckins(c *gin.Context) {
	var req model.CheckinListReq
	if err := c.ShouldBindQuery(&req); err != nil {
		response.Error(c, http.StatusBadRequest, "参数错误: "+err.Error())
		return
	}

	// 从上下文中获取会员ID
	memberID := uint(1) // 示例值，实际应从token中获取

	resp, err := h.checkinService.GetMemberCheckins(memberID, &req)
	if err != nil {
		response.Error(c, http.StatusInternalServerError, err.Error())
		return
	}

	response.Success(c, resp, "获取成功")
}

// GetCheckinStatistics 签到统计概览
// @Summary 签到统计概览
// @Description 获取当前会员的签到统计数据，包括本月签到天数、累计时长等
// @Tags 签到打卡
// @Produce json
// @Security ApiKeyAuth
// @Param period query string false "统计周期（day/week/month，默认month）"
// @Success 200 {object} response.Response{data=model.CheckinStatisticsResp}
// @Failure 400 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /api/v1/checkins/statistics [get]
func (h *CheckinHandler) GetCheckinStatistics(c *gin.Context) {
	var req model.CheckinStatisticsReq
	if err := c.ShouldBindQuery(&req); err != nil {
		response.Error(c, http.StatusBadRequest, "参数错误: "+err.Error())
		return
	}

	// 从上下文中获取会员ID
	memberID := uint(1) // 示例值，实际应从token中获取

	resp, err := h.checkinService.GetCheckinStatistics(memberID, &req)
	if err != nil {
		response.Error(c, http.StatusInternalServerError, err.Error())
		return
	}

	response.Success(c, resp, "获取成功")
}

// ==================== 前台接口 ====================

// GetStaffCheckins 前台查看签到列表
// @Summary 前台查看签到列表
// @Description 前台查看今日签到列表，支持按会员搜索和状态筛选
// @Tags 签到打卡
// @Produce json
// @Security ApiKeyAuth
// @Param page query int false "页码（默认1）"
// @Param pageSize query int false "每页数量（默认20，最大100）"
// @Param date query string false "日期（YYYY-MM-DD，默认今天）"
// @Param status query int false "状态（1:已签到未签退 2:已签退）"
// @Param keyword query string false "搜索关键词（会员姓名/卡号）"
// @Success 200 {object} response.Response{data=model.StaffCheckinListResp}
// @Failure 400 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /api/v1/staff/checkins [get]
func (h *CheckinHandler) GetStaffCheckins(c *gin.Context) {
	var req model.StaffCheckinListReq
	if err := c.ShouldBindQuery(&req); err != nil {
		response.Error(c, http.StatusBadRequest, "参数错误: "+err.Error())
		return
	}

	resp, err := h.checkinService.GetStaffCheckins(&req)
	if err != nil {
		response.Error(c, http.StatusInternalServerError, err.Error())
		return
	}

	response.Success(c, resp, "获取成功")
}

// CreateStaffCheckin 前台代会员签到
// @Summary 前台代会员签到
// @Description 前台工作人员代会员签到，支持扫卡、输入卡号、搜索会员
// @Tags 签到打卡
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param checkin body model.StaffCheckinReq true "前台代签到请求参数"
// @Success 200 {object} response.Response{data=model.StaffCheckinResp}
// @Failure 400 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /api/v1/staff/checkins [post]
func (h *CheckinHandler) CreateStaffCheckin(c *gin.Context) {
	var req model.StaffCheckinReq
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, http.StatusBadRequest, "参数错误: "+err.Error())
		return
	}

	// 从上下文中获取操作员ID
	operatorID := uint(1) // 示例值，实际应从token中获取

	resp, err := h.checkinService.CreateStaffCheckin(operatorID, &req)
	if err != nil {
		response.Error(c, http.StatusInternalServerError, err.Error())
		return
	}

	response.Success(c, resp, "签到成功")
}

// ==================== 管理员接口 ====================

// GetAdminCheckins 管理员查看所有签到
// @Summary 管理员查看所有签到
// @Description 管理员查看所有签到记录，支持多维度筛选和搜索
// @Tags 签到打卡
// @Produce json
// @Security ApiKeyAuth
// @Param page query int false "页码（默认1）"
// @Param pageSize query int false "每页数量（默认20，最大100）"
// @Param memberId query int false "会员ID筛选"
// @Param startDate query string false "开始日期（YYYY-MM-DD）"
// @Param endDate query string false "结束日期（YYYY-MM-DD）"
// @Param location query string false "签到地点筛选"
// @Param type query int false "类型筛选（1:进馆 2:签退）"
// @Param keyword query string false "搜索关键词（会员姓名/卡号）"
// @Success 200 {object} response.Response{data=model.AdminCheckinListResp}
// @Failure 400 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /api/v1/admin/checkins [get]
func (h *CheckinHandler) GetAdminCheckins(c *gin.Context) {
	var req model.AdminCheckinListReq
	if err := c.ShouldBindQuery(&req); err != nil {
		response.Error(c, http.StatusBadRequest, "参数错误: "+err.Error())
		return
	}

	resp, err := h.checkinService.GetAdminCheckins(&req)
	if err != nil {
		response.Error(c, http.StatusInternalServerError, err.Error())
		return
	}

	response.Success(c, resp, "获取成功")
}

// GetAdminAnalytics 签到数据统计分析
// @Summary 签到数据统计分析
// @Description 签到数据多维度统计分析，包括日/周/月签到趋势、高峰时段分析等
// @Tags 签到打卡
// @Produce json
// @Security ApiKeyAuth
// @Param period query string false "统计周期（day/week/month/year，默认month）"
// @Param startDate query string false "开始日期（YYYY-MM-DD）"
// @Param endDate query string false "结束日期（YYYY-MM-DD）"
// @Success 200 {object} response.Response{data=model.AdminAnalyticsResp}
// @Failure 400 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /api/v1/admin/checkins/analytics [get]
func (h *CheckinHandler) GetAdminAnalytics(c *gin.Context) {
	var req model.AdminAnalyticsReq
	if err := c.ShouldBindQuery(&req); err != nil {
		response.Error(c, http.StatusBadRequest, "参数错误: "+err.Error())
		return
	}

	resp, err := h.checkinService.GetAdminAnalytics(&req)
	if err != nil {
		response.Error(c, http.StatusInternalServerError, err.Error())
		return
	}

	response.Success(c, resp, "获取成功")
}

// GenerateQRCode 生成签到二维码
// @Summary 生成签到二维码
// @Description 为指定健身房生成签到二维码，包含时效性
// @Tags 签到打卡
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param qrcode body model.GenerateQRCodeReq true "生成二维码请求参数"
// @Success 200 {object} response.Response{data=model.GenerateQRCodeResp}
// @Failure 400 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /api/v1/admin/checkins/qrcode [post]
func (h *CheckinHandler) GenerateQRCode(c *gin.Context) {
	var req model.GenerateQRCodeReq
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, http.StatusBadRequest, "参数错误: "+err.Error())
		return
	}

	resp, err := h.checkinService.GenerateQRCode(&req)
	if err != nil {
		response.Error(c, http.StatusInternalServerError, err.Error())
		return
	}

	response.Success(c, resp, "二维码生成成功")
}

// BatchCheckin 批量补签/删除签到
// @Summary 批量补签/删除签到
// @Description 管理员批量操作签到记录，支持补签和删除异常记录
// @Tags 签到打卡
// @Accept json
// @Produce json
// @Security ApiKeyAuth
// @Param batch body model.BatchCheckinReq true "批量操作签到请求参数"
// @Success 200 {object} response.Response{data=model.BatchCheckinResp}
// @Failure 400 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /api/v1/admin/checkins/batch [post]
func (h *CheckinHandler) BatchCheckin(c *gin.Context) {
	var req model.BatchCheckinReq
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, http.StatusBadRequest, "参数错误: "+err.Error())
		return
	}

	// 从上下文中获取操作员ID
	operatorID := uint(1) // 示例值，实际应从token中获取

	resp, err := h.checkinService.BatchCheckin(operatorID, &req)
	if err != nil {
		response.Error(c, http.StatusInternalServerError, err.Error())
		return
	}

	response.Success(c, resp, "批量操作成功")
}

// ==================== 工具接口 ====================

// ValidateLocation 验证地理位置
// @Summary 验证地理位置
// @Description 验证会员位置是否在健身房范围内
// @Tags 签到打卡
// @Produce json
// @Security ApiKeyAuth
// @Param gymId query int true "健身房ID"
// @Param latitude query number true "纬度"
// @Param longitude query number true "经度"
// @Param accuracy query number false "定位精度（米）"
// @Success 200 {object} response.Response{data=bool}
// @Failure 400 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /api/v1/checkins/validate-location [get]
func (h *CheckinHandler) ValidateLocation(c *gin.Context) {
	gymIDStr := c.Query("gymId")
	gymID, err := strconv.ParseUint(gymIDStr, 10, 32)
	if err != nil {
		response.Error(c, http.StatusBadRequest, "健身房ID格式错误")
		return
	}

	// 使用下划线变量来避免gymID未使用错误
	_ = gymID

	latitude, err := strconv.ParseFloat(c.Query("latitude"), 64)
	if err != nil {
		response.Error(c, http.StatusBadRequest, "纬度格式错误")
		return
	}

	longitude, err := strconv.ParseFloat(c.Query("longitude"), 64)
	if err != nil {
		response.Error(c, http.StatusBadRequest, "经度格式错误")
		return
	}

	accuracy := 10.0 // 默认精度10米
	if accStr := c.Query("accuracy"); accStr != "" {
		if acc, err := strconv.ParseFloat(accStr, 64); err == nil {
			accuracy = acc
		}
	}

	// 这里应该从数据库获取健身房的地理围栏信息
	// 为简化起见，我们使用示例值
	gymLat := 39.9042
	gymLng := 116.4074
	gymRadius := 50.0

	isValid := h.checkinService.ValidateLocation(latitude, longitude, gymLat, gymLng, gymRadius, accuracy)
	response.Success(c, isValid, "位置验证成功")
}

// ValidateQRCode 验证二维码
// @Summary 验证二维码
// @Description 验证二维码的有效性和时效性
// @Tags 签到打卡
// @Produce json
// @Security ApiKeyAuth
// @Param gymId query int true "健身房ID"
// @Param qrCode query string true "二维码内容"
// @Success 200 {object} response.Response{data=bool}
// @Failure 400 {object} response.Response
// @Failure 500 {object} response.Response
// @Router /api/v1/checkins/validate-qrcode [get]
func (h *CheckinHandler) ValidateQRCode(c *gin.Context) {
	gymIDStr := c.Query("gymId")
	gymID, err := strconv.ParseUint(gymIDStr, 10, 32)
	if err != nil {
		response.Error(c, http.StatusBadRequest, "健身房ID格式错误")
		return
	}

	// 使用下划线变量来避免gymID未使用错误
	_ = gymID

	qrCode := c.Query("qrCode")
	if qrCode == "" {
		response.Error(c, http.StatusBadRequest, "二维码内容不能为空")
		return
	}

	err = h.checkinService.ValidateQRCode(qrCode, uint(gymID))
	isValid := err == nil
	if !isValid {
		response.Error(c, http.StatusBadRequest, "二维码验证失败: "+err.Error())
		return
	}

	response.Success(c, isValid, "二维码验证成功")
}
